package JavaSE.MSB.Thread.C08_InterView;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
/**
 * 面试题：写一个固定容量同步容器，拥有put和get方法，以及getCount方法，
 * 能够支持2个生产者线程以及10个消费者线程的阻塞调用
 *
 * 同步容器1
 *
 * */
public class T09_MyContainer1<T>
{
    final private LinkedList<T> lists = new LinkedList<>();
    final private int MAX = 10; //最多10个元素
    private int count = 0;
    
    public synchronized void put(T t)
    {
        //生产够了就wait
        while (lists.size() == MAX)//这里必须用while
        {
            try
            {
                this.wait(); //effective java
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        
        lists.add(t);
        ++count;//必须加 synchronized
        this.notifyAll(); //通知所有的生产者和消费者，只有1个消费者进行消费
    }
    
    public synchronized T get()
    {
        T t = null;
        //没有可以消费的了，就等
        while (lists.size() == 0)
        {
            try
            {
                this.wait();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        t = lists.removeFirst();
        count--;
        this.notifyAll(); //通知所有的生产者和消费者，只有1个生产者进行生产
        return t;
    }
    
    public static void main(String[] args)
    {
        T09_MyContainer1<String> c = new T09_MyContainer1<>();
        //启动消费者线程
        for (int i = 0; i < 10; i++)
        {
            new Thread(() ->
            {
                for (int j = 0; j < 5; j++) System.out.println(c.get());
            }, "c" + i).start();
        }
        
        try
        {
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        
        //启动生产者线程
        for (int i = 0; i < 2; i++)
        {
            new Thread(() ->
            {
                for (int j = 0; j < 25; j++) c.put(Thread.currentThread().getName() + " " + j);
            }, "p" + i).start();
        }
    }
}
